package com.sk.bilibili.factory;

import com.sk.bilibili.annotation.DefaultValue;
import com.sk.bilibili.property.MinioProperty;
import lombok.SneakyThrows;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author 邵康
 * @date 2021/12/6 9:06
 * 主要用于处理Bean的默认值注解
 */
@Component
public class DefaultValueFactory extends DefaultObjectFactory implements InitializingBean {

    @Autowired
    private MinioProperty minioProperty;
    private Map<Class,Map<Field,String>> fieldMap;
    private Set<Class> hasProcess;

    @Override
    public <T> T create(Class<T> type) {
        T t = super.create(type);
        fillDefaultValue(type,t);
        return t;
    }

    @SneakyThrows
    private <T> void fillDefaultValue(Class<T> type, T t) {
        if(!hasProcess.contains(type))processClass(type);
        if(!fieldMap.containsKey(type))return;
        Map<Field, String> map = fieldMap.get(type);
        for (Field field:map.keySet()){
            field.set(t, minioProperty.getBasePath()+map.get(field));
        }
    }

    private <T> void processClass(Class<T> type) {
        hasProcess.add(type);
        Field[] fields = type.getDeclaredFields();
        Map<Field,String> map=new HashMap<>();
        for (Field field:fields){
            DefaultValue defaultValue = field.getAnnotation(DefaultValue.class);
            if(defaultValue!=null){
                field.setAccessible(true);
                map.put(field,defaultValue.value());
            }
        }
        if(!map.isEmpty())fieldMap.put(type,map);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        fieldMap=new HashMap<>();
        hasProcess=new HashSet<>();
    }

}
